﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Net.Http;
using System.Threading;
using Common.Logging;
using In.Api.Dto.HisWs;
using Newtonsoft.Json;
using OutDbContext;
using Rmq.Center;
using User.Api.BizExtensions;
using User.Api.Helpers;
using User.Api.HttpClients;

namespace Out.TaskRunner.RmqWorkers
{
    public class OrderPickupingWorker : IWorker
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(OrderPickupingWorker));

        public void Start(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }

            using (var consumer = new OrderPickupingConsumer())
            {
                consumer.Subscribe((id, count, dt, msg, channel) =>
                {
                    if (msg.OrderType == OrderType.挂号订单)
                    {
                        return ProcessRegOrder(msg.OrderId, channel);
                    }
                    else if (msg.OrderType == OrderType.门诊缴费订单)
                    {
                        return ProcessBillOrder(msg.OrderId, channel);
                    }
                    else if (msg.OrderType == OrderType.住院预缴金订单)
                    {
                        return ProcessInpatientPrepayOrder(msg.OrderId, channel);
                    }

                    return new ConsumedResult { Ack = true };
                });

                while (true)
                {
                    if (ct.IsCancellationRequested)
                    {
                        break;
                    }

                    Thread.Sleep(50);
                }
            }
        }

        private ConsumedResult ProcessRegOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new FsssdqfybjyEntities())
            {
                var order = ctx.ApptOrders.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                var apptOrderType = order.OrderType;

                // 预约订单(微信或其他平台的预约)
                if (apptOrderType == ApptOrderExtensions.OrderType.预约.ToInt32().ToString()
                    || apptOrderType == ApptOrderExtensions.OrderType.其它平台预约.ToInt32().ToString())
                {
                    // 取号中
                    order.OrderStatus = ApptOrderExtensions.OrderStatus.取号中.ToInt32();
                    ctx.SaveChanges();

                    //执行预约报到操作
                    var request4CheckInBookInfo = new Request4CheckInBookInfo();
                    request4CheckInBookInfo.FlowNo = order.RegNo;
                    request4CheckInBookInfo.RegistrarId = "008881";
                    //******mod by boren 2015.12.3 传订单号 **********//
                    //request4CheckInBookInfo.MachineId = "008881";
                    request4CheckInBookInfo.MachineId = order.OrderNo;

                    Response4CheckInBookInfo response4CheckInBookInfo;
                    try
                    {
                        var httpClient = InHttpClient.GetClient();
                        var responseMsg = httpClient.PostAsJsonAsync("HisWs/CheckInBookInfo", request4CheckInBookInfo).Result;
                        responseMsg.EnsureSuccessStatusCode();
                        response4CheckInBookInfo = responseMsg.Content.ReadAsAsync<Response4CheckInBookInfo>().Result;
                    }
                    catch (Exception ex)
                    {
                        Logger.ErrorFormat("调用院内 CheckInBookInfo Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                        // RMQ 执行取号结果查询
                        var pickupingChkProducer = new OrderPickupingChkProducer();
                        pickupingChkProducer.Publish(new OrderPickupingChkMsg
                        {
                            OrderType = Rmq.Center.OrderType.挂号订单,
                            OrderId = order.Id
                        }, 5 * 60 * 1000);

                        return new ConsumedResult
                        {
                            Ack = true
                        };
                    }

                    if (response4CheckInBookInfo.ResultCode != "0")
                    {
                        // 取号失败
                        order.OrderStatus = ApptOrderExtensions.OrderStatus.取号失败.ToInt32();
                        order.Remark = response4CheckInBookInfo.ResultDesc;
                        ctx.SaveChanges();

                        Logger.ErrorFormat("预约取号订单号：{0}，取号失败,原因：{1}", order.OrderNo, response4CheckInBookInfo.ResultDesc);

                        // RMQ 发送用户挂号失败通知
                        var msgProducer = new UserMessageProducer();
                        msgProducer.Publish(new UserMessageMsg
                        {
                            Type = UserMessageType.挂号失败通知,
                            OrderId = order.Id
                        });

                        // RMQ 执行退费操作
                        if (order.SumFee > 0)
                        {
                            var refundingProducer = new OrderRefundingPickupFailedProducer();
                            refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                            {
                                OrderType = OrderType.挂号订单,
                                OrderId = order.Id
                            });
                        }
                    }
                    else
                    {
                        // 取号成功
                        order.OrderStatus = ApptOrderExtensions.OrderStatus.取号成功.ToInt32();
                        order.FlowNo = response4CheckInBookInfo.RegInfo.RegFlowNo;
                        order.WaitNo = response4CheckInBookInfo.RegInfo.WaitNo;
                        order.WaitCount = response4CheckInBookInfo.RegInfo.WaitCount;
                        order.PatType = response4CheckInBookInfo.RegInfo.PatType;
                        order.Location = response4CheckInBookInfo.RegInfo.Address;
                        order.FetchTime = DateTime.Now; //response4CheckInBookInfo.RegInfo.RegTime;
                        order.Remark = response4CheckInBookInfo.RegInfo.ResultMark;
                        ctx.SaveChanges();

                        // RMQ 发送用户挂号成功通知
                        var messageProducer = new UserMessageProducer();
                        messageProducer.Publish(new UserMessageMsg
                        {
                            Type = UserMessageType.挂号成功通知,
                            OrderId = order.Id
                        });

                        // RMQ 发送发货通知
                        if (order.SumFee > 0)
                        {
                            var wxuser = ctx.WxUsers.FirstOrDefault(x => x.Id == order.WxUserId);
                            if (wxuser != null)
                            {
                                WeixinPayV3Helper.DoDeliveryNotify(wxuser.OpenId, order.WxTransactionId,
                               "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                                                .ToString(), "1", "");
                            }
                        }
                    }

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                // 直接挂号
                if (apptOrderType == ApptOrderExtensions.OrderType.直接挂号.ToInt32().ToString())
                {
                    // 取号中
                    order.OrderStatus = ApptOrderExtensions.OrderStatus.取号中.ToInt32();
                    ctx.SaveChanges();

                    //执行取号操作
                    var request4SaveRegInfo = new Request4SaveRegInfo();
                    request4SaveRegInfo.HosPatId = "";
                    request4SaveRegInfo.ClinNo = "";
                    request4SaveRegInfo.IdCard = "";
                    request4SaveRegInfo.CardNo = order.CardNo;
                    request4SaveRegInfo.ScheduleId = order.ScheduleId;
                    request4SaveRegInfo.DeptId = order.DeptId;
                    request4SaveRegInfo.DoctorId = order.DoctorId;
                    request4SaveRegInfo.SubjectId = order.SubjectId;
                    request4SaveRegInfo.RegAmt = order.SumFee.ToString();
                    request4SaveRegInfo.SbConfirmed = order.SbConfirmed;
                    request4SaveRegInfo.RegistrarId = "008881";

                    //******mod by boren 2015.12.3 传订单号 **********//
                    //request.MachineId = "008881";
                    request4SaveRegInfo.MachineId = order.OrderNo;
                    request4SaveRegInfo.StartTime = order.StartTime;
                    request4SaveRegInfo.EndTime = order.EndTime;

                    Response4SaveRegInfo response4ExeRegister;

                    try
                    {
                        var httpClient = InHttpClient.GetClient();
                        var responseMsg = httpClient.PostAsJsonAsync("HisWs/SaveRegInfo", request4SaveRegInfo).Result;
                        responseMsg.EnsureSuccessStatusCode();
                        response4ExeRegister = responseMsg.Content.ReadAsAsync<Response4SaveRegInfo>().Result;
                    }
                    catch (Exception ex)
                    {
                        Logger.ErrorFormat("调用院内SaveRegInfo Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                        // RMQ 执行取号结果查询
                        var pickupingChkProducer = new OrderPickupingChkProducer();
                        pickupingChkProducer.Publish(new OrderPickupingChkMsg
                        {
                            OrderType = Rmq.Center.OrderType.挂号订单,
                            OrderId = order.Id
                        }, 5 * 60 * 1000);

                        return new ConsumedResult
                        {
                            Ack = true
                        };
                    }

                    if (response4ExeRegister.ResultCode != "0")
                    {
                        // 取号失败
                        order.OrderStatus = ApptOrderExtensions.OrderStatus.取号失败.ToInt32();
                        order.Remark = response4ExeRegister.ResultDesc;
                        ctx.SaveChanges();

                        Logger.ErrorFormat("直接挂号订单号：{0}，取号失败,原因：{1}", order.OrderNo, response4ExeRegister.ResultDesc);

                        // RMQ 发送用户挂号失败通知
                        var msgProducer = new UserMessageProducer();
                        msgProducer.Publish(new UserMessageMsg
                        {
                            Type = UserMessageType.挂号失败通知,
                            OrderId = order.Id
                        });

                        // RMQ 执行退费操作
                        if (order.SumFee > 0)
                        {
                            var refundingProducer = new OrderRefundingPickupFailedProducer();
                            refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                            {
                                OrderType = OrderType.挂号订单,
                                OrderId = order.Id
                            });
                        }
                    }
                    else
                    {
                        // 取号成功
                        order.OrderStatus = ApptOrderExtensions.OrderStatus.取号成功.ToInt32();
                        order.FlowNo = response4ExeRegister.FlowNo;
                        order.WaitNo = response4ExeRegister.WaitNo;
                        order.WaitCount = response4ExeRegister.WaitCount;
                        order.PatType = response4ExeRegister.PatType;
                        order.Location = response4ExeRegister.Address;
                        /* 增加挂号就诊时间 */
                        order.SuggestBeginTime = response4ExeRegister.PredictTime;
                        order.FetchTime = response4ExeRegister.RegTime.ToDateTimeOrDefault();
                        ctx.SaveChanges();


                        // RMQ 发送用户挂号成功通知
                        var messageProducer = new UserMessageProducer();
                        messageProducer.Publish(new UserMessageMsg
                        {
                            Type = UserMessageType.挂号成功通知,
                            OrderId = order.Id
                        });

                        // RMQ 发送发货通知
                        if (order.SumFee > 0)
                        {
                            var wxuser = ctx.WxUsers.FirstOrDefault(x => x.Id == order.WxUserId);
                            if (wxuser != null)
                            {
                                WeixinPayV3Helper.DoDeliveryNotify(wxuser.OpenId, order.WxTransactionId,
                               "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                                                .ToString(), "1", "");
                            }
                        }
                    }

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessBillOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new FsssdqfybjyEntities())
            {
                var order = ctx.ClinRecipeOrders.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                // 缴费中
                order.OrderStatus = BillOrderExtensions.OrderStatus.缴费中.ToInt32();
                ctx.SaveChanges();

                var orderItemList = ctx.ClinRecipeOrderItems.Where(x => x.ClinRecipeOrderId == orderId).ToList();
                //执行缴费操作
                var request = new Request4ClinPayFinish();
                request.HosPatId = "";
                request.ClinNo = "";
                request.IdCard = "";
                request.CardNo = order.CardNo;
                request.RecipeIds = order.RecipeIds;
                request.PayAmt = order.PayAmt;
                request.BankCardNo = order.BankCardNo;
                request.PayDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                request.CashierId = order.CashierId;
                //************Mod by boren 2015-12-03***************//
                // request.MachineId = order.MachineId;
                request.MachineId = order.OrderNo;

                request.Request4ClinPayFinishSubRecipeIdInfoList = new List<Request4ClinPayFinishSubRecipeIdInfo>();

                foreach (var orderItem in orderItemList)
                {
                    request.Request4ClinPayFinishSubRecipeIdInfoList.Add(new Request4ClinPayFinishSubRecipeIdInfo
                    {
                        FlowNo = orderItem.FlowNo,
                        RecipeId = orderItem.RecipeId,
                        PayType = orderItem.PayType,
                        TotalAmt = orderItem.TotalAmt,
                        SelfAmt = orderItem.SelfAmt,
                        SbPayAmt = orderItem.SbPayAmt,
                    });
                }


                Response4ClinPayFinish response4ClinPayFinish;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisWs/ClinPayFinish", request).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response4ClinPayFinish = responseMsg.Content.ReadAsAsync<Response4ClinPayFinish>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内ClinPayFinish Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    // RMQ 执行缴费状态结果查询
                    var pickupingChkProducer = new OrderPickupingChkProducer();
                    pickupingChkProducer.Publish(new OrderPickupingChkMsg
                    {
                        OrderType = Rmq.Center.OrderType.门诊缴费订单,
                        OrderId = order.Id
                    }, 5 * 60 * 1000);

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                if (response4ClinPayFinish.ResultCode != "0")
                {
                    // 缴费失败
                    order.OrderStatus = BillOrderExtensions.OrderStatus.缴费失败.ToInt32();
                    order.Remark = response4ClinPayFinish.ResultDesc;
                    ctx.SaveChanges();

                    Logger.ErrorFormat("门诊缴费订单号：{0}，缴费失败,原因：{1}", order.OrderNo, response4ClinPayFinish.ResultDesc);

                    // RMQ 发起缴费失败通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.缴费失败通知
                    });

                    // RMQ 发起退款
                    var refundingProducer = new OrderRefundingPickupFailedProducer();
                    refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                    {
                        OrderType = OrderType.门诊缴费订单,
                        OrderId = order.Id
                    });

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                else
                {
                    // 缴费成功
                    order.OrderStatus = BillOrderExtensions.OrderStatus.缴费成功.ToInt32();
                    order.HosPayId = response4ClinPayFinish.HosPayId;
                    order.InvoiceNo = response4ClinPayFinish.InvoiceNo;
                    order.ResultMark = response4ClinPayFinish.ResultMark;
                    order.TotalAmt = response4ClinPayFinish.TotalAmt;
                    order.SelfAmt = response4ClinPayFinish.SelfAmt;
                    order.SbPayAmt = response4ClinPayFinish.SbPayAmt;
                    order.FetchTime = DateTime.Now;

                    foreach (var resultData in response4ClinPayFinish.ResultDataList)
                    {
                        var newClinRecipeResultData = new ClinRecipeResultData
                        {
                            ClinRecipeId = order.Id,
                            HosPayId = resultData.HosPayId,
                            FeeType = resultData.FeeType,
                            TotalAmt = resultData.TotalAmt,
                            SelfAmt = resultData.SelfAmt
                        };

                        ctx.ClinRecipeResultDatas.Add(newClinRecipeResultData);
                    }

                    foreach (var executeInfo in response4ClinPayFinish.ExecuteInfoList)
                    {
                        var newClinRecipeExecuteInfo = new ClinRecipeExecuteInfo
                        {
                            ClinRecipeId = order.Id,
                            HosPayId = executeInfo.HosPayId,
                            RecipeIds = executeInfo.RecipeIds,
                            DeptHisCode = executeInfo.DeptHisCode,
                            DeptName = executeInfo.DeptName,
                            ExecType = executeInfo.ExecType,
                            Message = executeInfo.Message
                        };

                        ctx.ClinRecipeExecuteInfoes.Add(newClinRecipeExecuteInfo);
                    }
                    ctx.SaveChanges();

                    // RMQ 发起缴费成功通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.缴费成功通知
                    });
                    var wxuser = ctx.WxUsers.FirstOrDefault(x => x.Id == order.WxUserId);
                    if (wxuser != null)
                    {
                        // RMQ 发送发货通知
                        WeixinPayV3Helper.DoDeliveryNotify(wxuser.OpenId, order.WxTransactionId,
                       "BL" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                                        .ToString(), "1", "");
                    }
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessInpatientPrepayOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new FsssdqfybjyEntities())
            {
                var order = ctx.InpatientPrepayOrders.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                // 缴费中
                order.OrderStatus = PrepayOrderExtensions.OrderStatus.缴费中.ToInt32();
                ctx.SaveChanges();

                // 执行缴费操作
                var request = new Request4SetWardPreplay();
                request.WardNo = order.WardNo;
                request.PreCost = order.PrepayMoney.ToString();

                Response4SetWardPreplay response;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisWs/SetWardPreplay", request).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response = responseMsg.Content.ReadAsAsync<Response4SetWardPreplay>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内缴纳预缴金Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    // RMQ 执行缴费状态结果查询
                    var pickupingChkProducer = new OrderPickupingChkProducer();
                    pickupingChkProducer.Publish(new OrderPickupingChkMsg
                    {
                        OrderType = Rmq.Center.OrderType.住院预缴金订单,
                        OrderId = order.Id
                    }, 5 * 60 * 1000);

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                if (response.ResultCode != "0")
                {
                    // 缴费失败
                    order.OrderStatus = PrepayOrderExtensions.OrderStatus.缴费失败.ToInt32();
                    order.Remark = response.ResultDesc;
                    ctx.SaveChanges();

                    Logger.ErrorFormat("住院预缴金订单号：{0}，住院预缴金缴费失败,原因：{1}", order.OrderNo, response.ResultDesc);

                    // RMQ 发起住院预缴金失败通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.住院预缴金失败通知
                    });

                    // RMQ 发起退款
                    var refundingProducer = new OrderRefundingPickupFailedProducer();
                    refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                    {
                        OrderType = OrderType.住院预缴金订单,
                        OrderId = order.Id
                    });

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                else
                {
                    // 缴费成功
                    order.OrderStatus = PrepayOrderExtensions.OrderStatus.缴费成功.ToInt32();                    
                    order.FetchTime = DateTime.Now;
                    ctx.SaveChanges();

                    // RMQ 发起住院预缴金成功通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.住院预缴金成功通知
                    });

                    // RMQ 发送发货通知
                    var wxuser = ctx.WxUsers.FirstOrDefault(x => x.Id == order.WxUserId);
                    if (wxuser != null)
                    {
                        WeixinPayV3Helper.DoDeliveryNotify(wxuser.OpenId, order.WxTransactionId,
                       "IP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                                        .ToString(), "1", "");
                    }
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }
    }
}